home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d12 / bsrc_p2.arc / ZSEND.C < prev    next >
Encoding:
C/C++ Source or Header  |  1988-11-30  |  34.7 KB  |  845 lines

  1. /*--------------------------------------------------------------------------*/
  2. /* FILE: zsend.c    (Opus zmodem transmitter)                               */
  3. /*                                                                          */
  4. /*                                                                          */
  5. /*               The Opus Computer-Based Conversation System                */
  6. /*       (c) Copyright 1986, Wynn Wagner III, All Rights Reserved           */
  7. /*                                                                          */
  8. /*      This implementation of Chuck Forsberg's ZMODEM protocol was         */
  9. /*              for Opus by Rick Huebner and Wynn Wagner III                */
  10. /*                                                                          */
  11. /* (MSC/4 with /Zp /Ox)                                                     */
  12. /*                                                                          */
  13. /*                                                                          */
  14. /*                                                                          */
  15. /*                                                                          */
  16. /*  This module is similar to a routine used by Opus-Cbcs (1.00).  It is    */
  17. /*  provided for your information only.  You will find routines that need   */
  18. /*  to be coded and identifiers to be resolved.                             */
  19. /*                                                                          */
  20. /*  There is absolutely no guarantee that anything here will work.  If you  */
  21. /*  break this routine, you own both pieces.                                */
  22. /*                                                                          */
  23. /*  USAGE:  You may use this material in any program with no obligation     */
  24. /*          as long as there is no charge for your program.  For more       */
  25. /*          information about commercial use, contact the "OPUSinfo HERE"   */
  26. /*          BBS (124/111).                                                  */
  27. /*                                                                          */
  28. /*  NOTE:   There are a couple of things the Opus implementation does that  */
  29. /*          aren't part of the original ZModem protocol.  They all deal     */
  30. /*          with WaZOO type ("ZedZap") netmail and should only show up when */
  31. /*          used under that condition.                                      */
  32. /*                                                                          */
  33. /*             * The maximum packet size can grow larger than 1k.  It is    */
  34. /*               sensitive to the baud rate.  (2400b=2048k; 9600b=8192k)    */
  35. /*             * The sender must be able to send nothing.  In other words,  */
  36. /*               the sending system must be able to initiate and terminate  */
  37. /*               a zmodem send session without having to actually send a    */
  38. /*               file.  Normally this kind of thing would never happen in   */
  39. /*               zmodem.                                                    */
  40. /*                                                                          */
  41. /*                                                                          */
  42. /*--------------------------------------------------------------------------*/
  43.  
  44. #include "zmodem.h"
  45. #include "com.h"
  46.  
  47.  
  48. /*--------------------------------------------------------------------------*/
  49. /* Global routines                                                          */
  50. /*--------------------------------------------------------------------------*/
  51. int cdecl send_Zmodem(byte *,byte *,int,int,int);
  52.  
  53.  
  54. /*--------------------------------------------------------------------------*/
  55. /* Private routines                                                         */
  56. /*--------------------------------------------------------------------------*/
  57. static void pascal ZS_SendBinaryHeader(unsigned short ,byte *);
  58. static void pascal ZS_SendData(byte *,int,unsigned short);
  59. static void pascal ZS_SendByte(byte);
  60. static int  pascal ZS_GetReceiverInfo(void);
  61. static int  pascal ZS_SendFile(int,int);
  62. static int  pascal ZS_SendFileData(int);
  63. static int  pascal ZS_SyncWithReceiver(void);
  64. static void pascal ZS_EndSend(void);
  65.  
  66.  
  67.  
  68. /*--------------------------------------------------------------------------*/
  69. /* Private data                                                             */
  70. /*--------------------------------------------------------------------------*/
  71. static FILE *Infile;             /* Handle of file being sent               */
  72. static byte *Txbuf;              /* Pointer to transmit buffer              */
  73. static long  Strtpos;            /* Starting byte position of download      */
  74. static long  Txpos;              /* Transmitted file position               */
  75. static int Rxbuflen;             /* Receiver's max buffer length            */
  76.  
  77.  
  78. /*--------------------------------------------------------------------------*/
  79. /* External data not otherwise declared                                     */
  80. /*--------------------------------------------------------------------------*/
  81. extern char *FLAGGING_msg;
  82. extern char *NOTSENT_msg;
  83. extern char *TRUNC_msg;
  84. extern char *KBD_msg;
  85.  
  86. extern int un_attended;
  87. extern int fullscreen;
  88.  
  89.  
  90.  
  91.  
  92.  
  93.  
  94. /*--------------------------------------------------------------------------*/
  95. /* SEND ZMODEM (send a file)                                                */
  96. /*   returns TRUE (1) for good xfer, FALSE (0) for bad                      */
  97. /*   sends one file per call; 'fsent' flags start and end of batch          */
  98. /*--------------------------------------------------------------------------*/
  99. int cdecl send_Zmodem(fname,alias,doafter,fsent,wazoo)
  100.    byte  *fname;
  101.    byte  *alias;
  102.    int   doafter;
  103.    int   fsent;
  104.    int   wazoo;
  105.    begin
  106.       register byte *p;
  107.       register byte *q;
  108.       struct stat    f;
  109.  
  110.       int   i;
  111.       int   rc;
  112.  
  113.  
  114.       if (un_attended && fullscreen)
  115.          gotoxy(0,13);
  116.  
  117.       _BRK_DISABLE();
  118.       XON_ENABLE();
  119.  
  120.       errno    =
  121.       z_size   = 0;
  122.       Infile   = NULL;
  123.       Txbuf    = NULL;
  124.  
  125.  
  126.  
  127.       if (fname) set_xy("");
  128.  
  129.       switch(fsent)
  130.          begin
  131.             case 0:
  132.             case NOTHING_TO_DO:  n_disable();
  133.                                  if (!wazoo)
  134.                                     begin
  135.                                        Z_PutString("rz\r");
  136.                                        Z_PutLongIntoHeader(0L);
  137.                                        Z_SendHexHeader(ZRQINIT, Txhdr);
  138.                                     end
  139.                                  Rxtimeout   = 200;
  140.                                  if (ZS_GetReceiverInfo() == ERROR) return FALSE;
  141.          end
  142.  
  143.  
  144.       Rxtimeout   = (int )(614400L/(long )cur_baud);
  145.  
  146.       if (Rxtimeout < 100) Rxtimeout = 100;
  147.  
  148.  
  149.       if (fname == NULL) goto Done;
  150.  
  151.       /*--------------------------------------------------------------------*/
  152.       /* Prepare the file for transmission.  Just ignore file open errors   */
  153.       /* because there may be other files that can be sent.                 */
  154.       /*--------------------------------------------------------------------*/
  155.       Filename = fname;
  156.       CLEAR_IOERR();
  157.       Infile   = fopen(Filename,read_binary);
  158.       if (got_error(OPEN_msg,Filename)) return OK;
  159.       
  160.       Txbuf    = zalloc();
  161.  
  162.       /*--------------------------------------------------------------------*/
  163.       /* Send the file                                                      */
  164.       /*--------------------------------------------------------------------*/
  165.       rc       = TRUE;
  166.  
  167.  
  168.       /*--------------------------------------------------------------------*/
  169.       /* Display outbound filename, size, and ETA for sysop                 */
  170.       /*--------------------------------------------------------------------*/
  171.       fstat(fileno(Infile), &f);
  172.  
  173.       if (un_attended && fullscreen)
  174.          {
  175.          clear_filetransfer();
  176.          gotoxy (0,13);
  177.          }
  178.       cprintf( "Z-Send %s, %ldb",Filename,f.st_size);
  179.  
  180.       i  = (int)(f.st_size*10/cur_baud+27)/54;
  181.       if (i) cprintf(", %d min.",i);
  182.  
  183.       set_xy(NULL);
  184.  
  185.       /*--------------------------------------------------------------------*/
  186.       /* Get outgoing file name; no directory path, lower case              */
  187.       /*--------------------------------------------------------------------*/
  188.       for (p=(alias!=NULL)?alias:Filename, q=Txbuf ; *p; )
  189.          begin
  190.             if ((*q++ = tolower(*p)) == '\\') q = Txbuf;
  191.             p++;
  192.          end
  193.  
  194.       *q++  = '\0';
  195.       p     = q;
  196.  
  197.       /*--------------------------------------------------------------------*/
  198.       /* Zero out remainder of file header packet                           */
  199.       /*--------------------------------------------------------------------*/
  200.       while (q < (Txbuf + KSIZE)) *q++ = '\0';
  201.  
  202.       /*--------------------------------------------------------------------*/
  203.       /* Store filesize, time last modified, and file mode in header packet */
  204.       /*--------------------------------------------------------------------*/
  205.       sprintf(p, "%lu %lo %o", f.st_size, f.st_mtime, f.st_mode);
  206.  
  207.       /*--------------------------------------------------------------------*/
  208.       /* Transmit the filename block and begin the download                 */
  209.       /*--------------------------------------------------------------------*/
  210.       throughput(0,0L);
  211.  
  212.  
  213.       /*--------------------------------------------------------------------*/
  214.       /* Check the results                                                  */
  215.       /*--------------------------------------------------------------------*/
  216.       switch( ZS_SendFile(1+strlen(p)+(p-Txbuf), wazoo) )
  217.          begin
  218.  
  219.             case ERROR: /*--------------------------------------------------*/
  220.                         /* Something tragic happened                        */
  221.                         /*--------------------------------------------------*/
  222.                         goto Err_Out;
  223.  
  224.  
  225.             case OK:    /*--------------------------------------------------*/
  226.                         /* File was sent                                    */
  227.                         /*--------------------------------------------------*/
  228.                         CLEAR_IOERR();
  229.                         fclose(Infile);
  230.                         got_error(CLOSE_msg,Filename);
  231.                         Infile   = NULL;
  232.  
  233.                         status_line( "+Sent-Z %s", Filename );
  234.  
  235.                         /*--------------------------------------------------*/
  236.                         /* Special WaZOO file handling following a          */
  237.                         /* successful transmission.                         */
  238.                         /*--------------------------------------------------*/
  239.                         switch(doafter)
  240.                            begin
  241.                               case DELETE_AFTER:   /*-----------------------*/
  242.                                                    /* Delete File           */
  243.                                                    /*-----------------------*/
  244.                                                    CLEAR_IOERR();
  245.                                                    unlink(Filename);
  246.                                                    got_error(UNLINK_msg,Filename);
  247.                                                    break;
  248.    
  249.                               case TRUNC_AFTER:    /*-----------------------*/
  250.                                                    /* Truncate File         */
  251.                                                    /*-----------------------*/
  252.                                                    CLEAR_IOERR();
  253.                                                    i = open(Filename,O_TRUNC,S_IWRITE);
  254.                                                    got_error( TRUNC_msg, Filename );
  255.                                                    status_line(FLAGGING_msg,Filename);
  256.                                                    close(i);
  257.                                                    break;
  258.                            end /* switch */
  259.  
  260.  
  261.             default:    /*--------------------------------------------------*/
  262.                         /* Probably a ZSKIP                                 */
  263.                         /*--------------------------------------------------*/
  264.                         goto Done;
  265.  
  266.          end /* switch */
  267.  
  268. Err_Out:
  269.       rc = FALSE;
  270.  
  271. Done:
  272.       if (Infile) fclose(Infile);
  273.       if (Txbuf)  free(Txbuf);
  274.  
  275.       if (fsent < 0) ZS_EndSend();
  276.  
  277.       return rc;
  278.  
  279.    end /* send_Zmodem */
  280.  
  281.  
  282.  
  283.  
  284.  
  285.  
  286. /*--------------------------------------------------------------------------*/
  287. /* ZS SEND BINARY HEADER                                                    */
  288. /* Send ZMODEM binary header hdr of type type                               */
  289. /*--------------------------------------------------------------------------*/
  290. static void pascal ZS_SendBinaryHeader(type, hdr)
  291.    unsigned short type;
  292.    register byte  *hdr;
  293.    begin
  294.       register unsigned short crc;
  295.       int                     n;
  296.  
  297.       SENDBYTE(ZPAD);
  298.       SENDBYTE(ZDLE);
  299.  
  300.       SENDBYTE(ZBIN);
  301.       ZS_SendByte(type);
  302.  
  303.       crc = Z_UpdateCRC(type, 0);
  304.  
  305.       for (n=4; --n >= 0;)
  306.          begin
  307.             ZS_SendByte(*hdr);
  308.             crc = Z_UpdateCRC(((unsigned short)(*hdr++)), crc);
  309.          end
  310. #ifdef NO_CRC_ASM
  311.       crc = Z_UpdateCRC(0,crc);
  312.       crc = Z_UpdateCRC(0,crc);
  313. #endif
  314.       ZS_SendByte(crc>>8);
  315.       ZS_SendByte(crc);
  316.  
  317.       if (type != ZDATA)
  318.          {
  319.          while (CARRIER && !OUT_EMPTY())
  320.             time_release();
  321.          if (!CARRIER)
  322.             CLEAR_OUTBOUND();
  323.          }
  324.  
  325.    end /* ZS_SendBinaryHeader */
  326.  
  327.  
  328.  
  329. /*--------------------------------------------------------------------------*/
  330. /* ZS SEND DATA                                                             */
  331. /* Send binary array buf with ending ZDLE sequence frameend                 */
  332. /*--------------------------------------------------------------------------*/
  333. static void pascal ZS_SendData(buf, length, frameend)
  334.    register byte  *buf;
  335.    int            length;
  336.    unsigned short frameend;
  337.    begin
  338.  
  339.       register unsigned short crc;
  340.       int                     t;
  341.  
  342.       crc = 0;
  343.       for (;--length >= 0;)
  344.          begin
  345.             ZS_SendByte(*buf);
  346.             crc = Z_UpdateCRC(((unsigned short)(*buf++)), crc);
  347.          end
  348.  
  349.       SENDBYTE(ZDLE);
  350.       SENDBYTE(frameend);
  351.       crc = Z_UpdateCRC(frameend, crc);
  352. #ifdef NO_CRC_ASM
  353.       crc = Z_UpdateCRC(0,crc);
  354.       crc = Z_UpdateCRC(0,crc);
  355. #endif
  356.       ZS_SendByte(crc>>8);
  357.       ZS_SendByte(crc);
  358.  
  359.       if (frameend == ZCRCW)
  360.          begin
  361.             SENDBYTE(XON);
  362.             while (CARRIER && !OUT_EMPTY())
  363.                time_release();
  364.             if (!CARRIER)
  365.                CLEAR_OUTBOUND();
  366.          end
  367.  
  368.    end /* ZS_SendData */
  369.  
  370.  
  371.  
  372.  
  373. /*--------------------------------------------------------------------------*/
  374. /* ZS SEND BYTE                                                             */
  375. /* Send character c with ZMODEM escape sequence encoding.                   */
  376. /* Escape XON, XOFF. Escape CR following @ (Telenet net escape)             */
  377. /*--------------------------------------------------------------------------*/
  378. static void pascal ZS_SendByte(c)
  379.    register byte c;
  380.    begin
  381.       static byte lastsent;
  382.  
  383.       switch (c)
  384.          begin
  385.             case 015:
  386.             case 0215:  /*--------------------------------------------------*/
  387.                         /*                                                  */
  388.                         /*--------------------------------------------------*/
  389.                         if ((lastsent & 0x7F) != '@') goto SendIt;
  390.             case 020:
  391.             case 021:
  392.             case 023:
  393.             case 0220:
  394.             case 0221:
  395.             case 0223:
  396.             case ZDLE:  /*--------------------------------------------------*/
  397.                         /* Quoted characters                                */
  398.                         /*--------------------------------------------------*/
  399.                         SENDBYTE(ZDLE);
  400.                         c ^= 0x40;
  401.  
  402.             default:    /*--------------------------------------------------*/
  403.                         /* Normal character output                          */
  404. SendIt:                 /*--------------------------------------------------*/
  405.                         SENDBYTE(lastsent = c);
  406.  
  407.          end /* switch */
  408.  
  409.    end /* ZS_SendByte */
  410.  
  411.  
  412.  
  413. /*--------------------------------------------------------------------------*/
  414. /* ZS GET RECEIVER INFO                                                     */
  415. /* Get the receiver's init parameters                                       */
  416. /*--------------------------------------------------------------------------*/
  417. static int pascal ZS_GetReceiverInfo()
  418.    begin
  419.       int   n;
  420.       int   rxflags;
  421.  
  422.       for (n=10; --n>=0; )
  423.          begin
  424.  
  425.             switch ( Z_GetHeader(Rxhdr) )
  426.                begin
  427.                   case ZCHALLENGE:  /*--------------------------------------*/
  428.                                     /* Echo receiver's challenge number     */
  429.                                     /*--------------------------------------*/
  430.                                     Z_PutLongIntoHeader(Rxpos);
  431.                                     Z_SendHexHeader(ZACK, Txhdr);
  432.                                     continue;
  433.  
  434.                   case ZCOMMAND:    /*--------------------------------------*/
  435.                                     /* They didn't see our ZRQINIT          */
  436.                                     /*--------------------------------------*/
  437.                                     Z_PutLongIntoHeader(0L);
  438.                                     Z_SendHexHeader(ZRQINIT, Txhdr);
  439.                                     continue;
  440.  
  441.                   case ZRINIT:      /*--------------------------------------*/
  442.                                     /*                                      */
  443.                                     /*--------------------------------------*/
  444.                                     Rxbuflen = ((word )Rxhdr[ZP1]<<8)|Rxhdr[ZP0];
  445.                                     return OK;
  446.  
  447.                   case ZCAN:
  448.                   case RCDO:
  449.                   case TIMEOUT:     /*--------------------------------------*/
  450.                                     /*                                      */
  451.                                     /*--------------------------------------*/
  452.                                     return ERROR;
  453.  
  454.                   case ZRQINIT:     /*--------------------------------------*/
  455.                                     /*                                      */
  456.                                     /*--------------------------------------*/
  457.                                     if (Rxhdr[ZF0] == ZCOMMAND) continue;
  458.  
  459.                   default:          /*--------------------------------------*/
  460.                                     /*                                      */
  461.                                     /*--------------------------------------*/
  462.                                     Z_SendHexHeader(ZNAK, Txhdr);
  463.                                     continue;
  464.                end /* switch */
  465.  
  466.          end /* for */
  467.  
  468.       return ERROR;
  469.  
  470.    end /* ZS_GetReceiverInfo */
  471.  
  472.  
  473.  
  474.  
  475.  
  476. /*--------------------------------------------------------------------------*/
  477. /* ZS SEND FILE                                                             */
  478. /* Send ZFILE frame and begin sending ZDATA frame                           */
  479. /*--------------------------------------------------------------------------*/
  480. static int pascal ZS_SendFile(blen, wazoo)
  481.    int blen;
  482.    int wazoo;
  483.    begin
  484.       register int c;
  485.  
  486.       while(1)
  487.  
  488.          begin
  489.  
  490.             if (((KEYPRESS()) and (READKB()==27)))
  491.                begin
  492.                   send_can();
  493.                   z_log( KBD_msg );
  494.                   return ERROR;
  495.                end
  496.             else if (!CARRIER) return ERROR;
  497.  
  498.    
  499.             Txhdr[ZF0] = LZCONV;    /* Default file conversion mode */
  500.             Txhdr[ZF1] = LZMANAG;   /* Default file management mode */
  501.             Txhdr[ZF2] = LZTRANS;   /* Default file transport mode */
  502.             Txhdr[ZF3] = 0;
  503.             ZS_SendBinaryHeader(ZFILE, Txhdr);
  504.             ZS_SendData(Txbuf, blen, ZCRCW);
  505.    
  506. Again:
  507.             switch (c = Z_GetHeader(Rxhdr))
  508.                begin
  509.  
  510.                   case ZRINIT:   /*-----------------------------------------*/
  511.                                  /*                                         */
  512.                                  /*-----------------------------------------*/
  513.                                  goto Again;
  514.  
  515.                   case ZCAN:     
  516.                   case ZCRC:     
  517.                   case RCDO:     
  518.                   case TIMEOUT:  
  519.                   case ZFIN:
  520.                   case ZABORT:   
  521.                                  /*-----------------------------------------*/
  522.                                  /*                                         */
  523.                                  /*-----------------------------------------*/
  524.                                  return ERROR;
  525.    
  526.                   case ZSKIP:    /*-----------------------------------------*/
  527.                                  /* Other system wants to skip this file    */
  528.                                  /*-----------------------------------------*/
  529.                                  return c;
  530.    
  531.                   case ZRPOS:    /*-----------------------------------------*/
  532.                                  /* Resend from this position...            */
  533.                                  /*-----------------------------------------*/
  534.                                  fseek(Infile, Rxpos, SEEK_SET);
  535.                                  if (Rxpos != 0L)
  536.                                     status_line (":Resuming from offset %ld", Rxpos);
  537.                                  Strtpos = Txpos = Rxpos;
  538.                                  CLEAR_INBOUND();
  539.                                  return ZS_SendFileData(wazoo);
  540.                end /* switch */
  541.  
  542.          end /* while */
  543.  
  544.    end /* ZS_SendFile */
  545.  
  546.  
  547.  
  548.  
  549. /*--------------------------------------------------------------------------*/
  550. /* ZS SEND FILE DATA                                                        */
  551. /* Send the data in the file                                                */
  552. /*--------------------------------------------------------------------------*/
  553. static int pascal ZS_SendFileData(wazoo)
  554.    int wazoo;
  555.    begin
  556.  
  557.       register int c, e;
  558.       word         newcnt, blklen, maxblklen, goodblks, goodneeded = 1;
  559.       byte        *p;
  560.  
  561.  
  562.       maxblklen = (cur_baud<300) ? 128 : cur_baud/300*256;
  563.  
  564.       if (maxblklen>WAZOOMAX)              maxblklen = WAZOOMAX;
  565.       if (!wazoo && maxblklen>KSIZE)       maxblklen = KSIZE;
  566.       if (Rxbuflen && maxblklen>Rxbuflen)  maxblklen = Rxbuflen;
  567.       blklen = maxblklen;
  568.  
  569.  
  570. SomeMore:
  571.  
  572.       if (CHAR_AVAIL())
  573.          begin
  574. WaitAck:
  575.  
  576.             switch (c = ZS_SyncWithReceiver())
  577.                begin
  578.                   default:       /*-----------------------------------------*/
  579.                                  /*                                         */
  580.                                  /*-----------------------------------------*/
  581.                                  z_log(Cancelled_msg);
  582.                                  errno = 0;
  583.                                  fclose(Infile);
  584.                                  got_error(CLOSE_msg,Filename);
  585.                                  return ERROR;
  586.  
  587.                   case ZSKIP:    /*-----------------------------------------*/
  588.                                  /* Skip this file                          */
  589.                                  /*-----------------------------------------*/
  590.                                  return c;
  591.  
  592.                   case ZACK:     /*-----------------------------------------*/
  593.                                  /*                                         */
  594.                                  /*-----------------------------------------*/
  595.                                  break;
  596.  
  597.                   case ZRPOS:    /*-----------------------------------------*/
  598.                                  /* Resume at this position                 */
  599.                                  /*-----------------------------------------*/
  600.                                  blklen = (blklen>>2 > 64) ? blklen>>2 : 64;
  601.                                  goodblks = 0;
  602.                                  goodneeded = (goodneeded<<1) | 1;
  603.                                  break;
  604.  
  605.                   case ZRINIT:   /*-----------------------------------------*/
  606.                                  /* Receive init                            */
  607.                                  /*-----------------------------------------*/
  608.                                  if (locate_y) gotoxy(0,(byte)locate_y-1);
  609.                                  throughput(1,Txpos-Strtpos);
  610.                                  return OK;
  611.                end /* switch */
  612.  
  613.             while (CHAR_AVAIL())
  614.                begin
  615.                   switch (MODEM_IN())
  616.                      begin
  617.                         case CAN:
  618.                         case RCDO:
  619.                         case ZPAD:  goto WaitAck;
  620.                      end /* switch */
  621.                end /* while */
  622.  
  623.          end /* while */
  624.  
  625.       newcnt = Rxbuflen;
  626.       Z_PutLongIntoHeader(Txpos);
  627.       ZS_SendBinaryHeader(ZDATA, Txhdr);
  628.  
  629.       do
  630.          begin
  631.  
  632.             if (((KEYPRESS()) and (READKB()==27)))
  633.                begin
  634.                   send_can();
  635.                   z_log( KBD_msg );
  636.                   goto oops;
  637.                end
  638.  
  639.             if (!CARRIER) goto oops;
  640.  
  641.             if ((c=fread(Txbuf,1,blklen,Infile))!=z_size)
  642.                begin
  643.                   gotoxy( locate_x+10, locate_y );
  644.                   cputs( ultoa(((unsigned long )(z_size=c)),e_input,10) );
  645.                   putch(' ');
  646.                end
  647.  
  648.             if (c < blklen) e = ZCRCE;
  649.             else if (Rxbuflen && (newcnt -= c) <= 0) e = ZCRCW;
  650.             else e = ZCRCG;
  651.  
  652.             ZS_SendData(Txbuf, c, e);
  653.  
  654.             gotoxy( locate_x, locate_y );
  655.             cputs( ultoa(((unsigned long )Txpos),e_input,10) );
  656.             putch(' ');
  657.  
  658.             Txpos += c;
  659.             if (blklen<maxblklen && ++goodblks>goodneeded)
  660.                begin
  661.                   blklen = (blklen<<1 < maxblklen) ? blklen<<1 : maxblklen;
  662.                   goodblks = 0;
  663.                end
  664.  
  665.             if (e == ZCRCW) goto WaitAck;
  666.  
  667.             while (CHAR_AVAIL())
  668.                begin
  669.                   switch (MODEM_IN())
  670.                      begin
  671.                         case CAN:
  672.                         case RCDO:
  673.                         case ZPAD:  /*--------------------------------------*/
  674.                                     /* Interruption detected;               */
  675.                                     /* stop sending and process complaint   */
  676.                                     /*--------------------------------------*/
  677.                                     z_message("Trouble?");
  678.                                     CLEAR_OUTBOUND();
  679.                                     ZS_SendData(Txbuf, 0, ZCRCE);
  680.                                     goto WaitAck;
  681.                      end /* switch */
  682.                end /* while */
  683.       
  684.          end /* do */
  685.       while (e == ZCRCG);
  686.  
  687.       while(1)
  688.          begin
  689.             Z_PutLongIntoHeader(Txpos);
  690.             ZS_SendBinaryHeader(ZEOF, Txhdr);
  691.  
  692.             switch (ZS_SyncWithReceiver())
  693.                begin
  694.                   case ZACK:     /*-----------------------------------------*/
  695.                                  /*                                         */
  696.                                  /*-----------------------------------------*/
  697.                                  continue;
  698.  
  699.                   case ZRPOS:    /*-----------------------------------------*/
  700.                                  /* Resume at this position...              */
  701.                                  /*-----------------------------------------*/
  702.                                  goto SomeMore;
  703.  
  704.                   case ZRINIT:   /*-----------------------------------------*/
  705.                                  /* Receive init                            */
  706.                                  /*-----------------------------------------*/
  707.                                  if (locate_y) gotoxy(0,(byte)locate_y-1);
  708.                                  throughput(1,Txpos-Strtpos);
  709.                                  return OK;
  710.  
  711.                   case ZSKIP:    /*-----------------------------------------*/
  712.                                  /* Request to skip the current file        */
  713.                                  /*-----------------------------------------*/
  714.                                  z_log(Skip_msg);
  715.                                  CLEAR_IOERR();
  716.                                  fclose(Infile);
  717.                                  got_error(CLOSE_msg,Filename);
  718.                                  return c;
  719.  
  720.                   default:       /*-----------------------------------------*/
  721.                                  /*                                         */
  722.                                  /*-----------------------------------------*/
  723. oops:                            z_log(Cancelled_msg);
  724.                                  errno = 0;
  725.                                  fclose(Infile);
  726.                                  got_error(CLOSE_msg,Filename);
  727.                                  return ERROR;
  728.                end /* switch */
  729.          end /* while */
  730.  
  731.    end /* ZS_SendFileData */
  732.  
  733.  
  734.  
  735.  
  736.  
  737.  
  738. /*--------------------------------------------------------------------------*/
  739. /* ZS SYNC WITH RECEIVER                                                    */
  740. /* Respond to receiver's complaint, get back in sync with receiver          */
  741. /*--------------------------------------------------------------------------*/
  742. static int pascal ZS_SyncWithReceiver()
  743.    begin
  744.       register int c;
  745.       int          num_errs   = 7;
  746.  
  747.       while(1)
  748.          begin
  749.             c = Z_GetHeader(Rxhdr);
  750.             CLEAR_INBOUND();
  751.             switch (c)
  752.                begin
  753.                   case TIMEOUT:  z_message( TIME_msg );
  754.                                  if ((num_errs--) >= 0) break;
  755.  
  756.                   case ZCAN:
  757.                   case ZABORT:
  758.                   case ZFIN:
  759.                   case RCDO:
  760.                                  /*-----------------------------------------*/
  761.                                  /*                                         */
  762.                                  /*-----------------------------------------*/
  763.                                  z_log("!Err");
  764.                                  return ERROR;
  765.  
  766.                   case ZRPOS:    /*-----------------------------------------*/
  767.                                  /*                                         */
  768.                                  /*-----------------------------------------*/
  769.                                  rewind(Infile);   /* In case file EOF seen */
  770.                                  fseek(Infile, Rxpos, SEEK_SET);
  771.                                  Txpos = Rxpos;
  772.                                  z_message(NULL);
  773.                                  cputs("Resending from ");
  774.                                  cputs( ultoa(((unsigned long )(Txpos)),e_input,10) );
  775.                                  return c;
  776.  
  777.                   case ZSKIP:    /*-----------------------------------------*/
  778.                                  /*                                         */
  779.                                  /*-----------------------------------------*/
  780.                                  z_log(Skip_msg);
  781.  
  782.                   case ZRINIT:   /*-----------------------------------------*/
  783.                                  /*                                         */
  784.                                  /*-----------------------------------------*/
  785.                                  CLEAR_IOERR();
  786.                                  fclose(Infile);
  787.                                  got_error(CLOSE_msg,Filename);
  788.                                  return c;
  789.  
  790.                   case ZACK:     /*-----------------------------------------*/
  791.                                  /*                                         */
  792.                                  /*-----------------------------------------*/
  793.                                  z_message( NULL );
  794.                                  return c;
  795.  
  796.                   default:       /*-----------------------------------------*/
  797.                                  /*                                         */
  798.                                  /*-----------------------------------------*/
  799.                                  z_message( IDUNNO_msg );
  800.                                  ZS_SendBinaryHeader(ZNAK, Txhdr);
  801.                                  continue;
  802.                end /* switch */
  803.          end /* while */
  804.    end /* ZS_SyncWithReceiver */
  805.  
  806.  
  807.  
  808.  
  809. /*--------------------------------------------------------------------------*/
  810. /* ZS END SEND                                                              */
  811. /* Say BIBI to the receiver, try to do it cleanly                           */
  812. /*--------------------------------------------------------------------------*/
  813. static void pascal ZS_EndSend()
  814.    begin
  815.  
  816.       while(1)
  817.          begin
  818.             Z_PutLongIntoHeader(0L);
  819.             ZS_SendBinaryHeader(ZFIN, Txhdr);
  820.  
  821.             switch (Z_GetHeader(Rxhdr))
  822.                begin
  823.                   case ZFIN:     /*-----------------------------------------*/
  824.                                  /*                                         */
  825.                                  /*-----------------------------------------*/
  826.                                  SENDBYTE('O');
  827.                                  SENDBYTE('O');
  828.                                  while (CARRIER && !OUT_EMPTY())
  829.                                     time_release();
  830.                                  if (!CARRIER)
  831.                                     CLEAR_OUTBOUND();
  832.                                  /* fallthrough... */
  833.                   case ZCAN:
  834.                   case RCDO:
  835.                   case TIMEOUT:  /*-----------------------------------------*/
  836.                                  /*                                         */
  837.                                  /*-----------------------------------------*/
  838.                                  return;
  839.                end /* switch */
  840.          end /* while */
  841.    end /* ZS_EndSend */
  842.  
  843.  
  844. /* END OF FILE: zsend.c */
  845.